package start.ofd;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.ofdrw.reader.OFDReader;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

/**
 * 数科表单设计器OFD处理工具（最小化实现，避免依赖问题）
 * 说明：使用基础Java类处理OFD（本质是ZIP压缩包），不依赖ofdrw的高级模块
 */
public class ShukeOFDynamicTableHandler {

    private static final String LINE_SEPARATOR = System.lineSeparator();
    private static final String CONTENT_DIR = "Content/";
    private static final String PAGES_DIR = CONTENT_DIR + "Pages/";

    public static void main(String[] args) {
        String templatePath = "D:\\temp\\template.ofd";
        String xmlDataPath = "D:\\temp\\data.xml";
        String outputPath = "D:\\temp\\result.ofd";

        try {
            System.out.println("开始处理OFD文件..." + LINE_SEPARATOR);

            // 1. 解析XML数据
            Map<String, Object> dataMap = parseXmlData(xmlDataPath);
            System.out.println("解析XML完成，数据项数量: " + dataMap.size());

            // 2. 验证模板文件
            validateFile(templatePath);
            System.out.println("模板文件验证通过: " + templatePath);

            // 3. 复制并处理OFD模板
            processOFD(templatePath, outputPath, dataMap);
            System.out.println(LINE_SEPARATOR + "处理完成，生成文件: " + Paths.get(outputPath).toAbsolutePath());

        } catch (Exception e) {
            System.err.println("处理失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 解析XML数据
     */
    @SuppressWarnings("unchecked")
    private static Map<String, Object> parseXmlData(String xmlPath) throws DocumentException, FileNotFoundException {
        SAXReader reader = new SAXReader();
        Document doc = reader.read(new FileInputStream(xmlPath));
        Element root = doc.getRootElement();

        return (Map<String, Object>) parseElement(root);
    }

    /**
     * 递归解析XML元素
     */
    private static Object parseElement(Element element) {
        List<Element> children = element.elements();
        if (children.isEmpty()) {
            return element.getTextTrim();
        }

        String firstChildName = children.get(0).getName();
        boolean isList = true;
        for (Element child : children) {
            if (!child.getName().equals(firstChildName)) {
                isList = false;
                break;
            }
        }

        if (isList) {
            List<Object> list = new ArrayList<>();
            for (Element child : children) {
                list.add(parseElement(child));
            }
            return list;
        } else {
            Map<String, Object> map = new HashMap<>();
            for (Element child : children) {
                map.put(child.getName(), parseElement(child));
            }
            return map;
        }
    }

    /**
     * 验证文件有效性
     */
    private static void validateFile(String path) throws IOException {
        Path file = Paths.get(path);
        if (!Files.exists(file)) {
            throw new FileNotFoundException("文件不存在: " + path);
        }
        if (!Files.isRegularFile(file)) {
            throw new IOException("不是有效文件: " + path);
        }
    }

    /**
     * 处理OFD文件（本质是ZIP压缩包）
     */
    private static void processOFD(String templatePath, String outputPath, Map<String, Object> data) throws IOException {
        // 创建临时目录存储解压后的内容
        Path tempDir = Files.createTempDirectory("ofd-process-");

        try {
            // 1. 解压OFD模板（OFD本质是符合特定规范的ZIP包）
            unzip(new File(templatePath), tempDir.toFile());
            System.out.println("模板解压完成，临时目录: " + tempDir);

            // 2. 处理页面内容
            processPages(tempDir, data);

            // 3. 重新压缩为OFD文件
            zip(tempDir.toFile(), new File(outputPath));
            System.out.println("重新压缩完成");

        } finally {
            // 清理临时文件
            deleteDir(tempDir.toFile());
        }
    }

    /**
     * 处理所有页面文件
     */
    private static void processPages(Path rootDir, Map<String, Object> data) throws IOException {
        File pagesDir = new File(rootDir.toFile() , "");
        if (!pagesDir.exists() || !pagesDir.isDirectory()) {
            throw new IOException("未找到页面目录: " + pagesDir);
        }

        // 遍历所有页面XML文件
        File[] pageFiles = pagesDir.listFiles((dir, name) -> name.endsWith(".xml"));
        if (pageFiles == null || pageFiles.length == 0) {
            System.out.println("未找到页面文件");
            return;
        }

        for (File pageFile : pageFiles) {
            System.out.println("处理页面文件: " + pageFile.getName());

            // 读取页面内容
            String content = new String(Files.readAllBytes(pageFile.toPath()), "UTF-8");

            // 替换占位符
            String processedContent = replacePlaceholders(content, data);

            // 处理动态表格
            processedContent = processDynamicTables(processedContent, data);

            // 写回文件
            Files.write(pageFile.toPath(), processedContent.getBytes("UTF-8"));
        }
    }

    /**
     * 替换内容中的占位符
     */
    private static String replacePlaceholders(String content, Map<String, Object> data) {
        String result = content;
        for (Map.Entry<String, Object> entry : data.entrySet()) {
            if (!(entry.getValue() instanceof List)) {
                String placeholder = "{{" + entry.getKey() + "}}";
                String value = entry.getValue() != null ? entry.getValue().toString() : "";
                result = result.replace(placeholder, escapeXml(value));
            }
        }
        return result;
    }

    /**
     * 处理动态表格
     */
    @SuppressWarnings("unchecked")
    private static String processDynamicTables(String content, Map<String, Object> data) {
        String result = content;
        for (Map.Entry<String, Object> entry : data.entrySet()) {
            if (entry.getValue() instanceof List) {
                List<Object> tableData = (List<Object>) entry.getValue();
                if (!tableData.isEmpty() && tableData.get(0) instanceof Map) {
                    result = generateTableRows(result, entry.getKey(), tableData);
                }
            }
        }
        return result;
    }

    /**
     * 生成动态表格行
     */
    private static String generateTableRows(String content, String tableId, List<Object> dataList) {
        String templateMarker = "<!-- TABLE_TEMPLATE:" + tableId + " -->";
        String endMarker = "<!-- TABLE_END:" + tableId + " -->";

        int startIdx = content.indexOf(templateMarker);
        int endIdx = content.indexOf(endMarker);

        if (startIdx == -1 || endIdx == -1) {
            System.out.println("未找到表格模板: " + tableId);
            return content;
        }

        String templateRow = content.substring(startIdx + templateMarker.length(), endIdx);
        StringBuilder rowsBuilder = new StringBuilder();

        for (Object item : dataList) {
            if (item instanceof Map) {
                Map<String, Object> rowData = (Map<String, Object>) item;
                String row = templateRow;
                for (Map.Entry<String, Object> entry : rowData.entrySet()) {
                    String placeholder = "{{" + entry.getKey() + "}}";
                    String value = entry.getValue() != null ? entry.getValue().toString() : "";
                    row = row.replace(placeholder, escapeXml(value));
                }
                rowsBuilder.append(row);
            }
        }

        return content.substring(0, startIdx) +
                rowsBuilder.toString() +
                content.substring(endIdx + endMarker.length());
    }

    /**
     * 解压ZIP文件（OFD本质是ZIP）
     */
    private static void unzip(File zipFile, File destDir) throws IOException {
        if (!destDir.exists()) {
            destDir.mkdirs();
        }
        try (ZipFile zf = new ZipFile(zipFile)) {
            Enumeration<? extends ZipEntry> entries = zf.entries();
            while (entries.hasMoreElements()) {
                ZipEntry entry = entries.nextElement();
                File entryFile = new File(destDir, entry.getName());
                if (entry.isDirectory()) {
                    entryFile.mkdirs();
                } else {
                    entryFile.getParentFile().mkdirs();
                    try (InputStream is = zf.getInputStream(entry);
                         OutputStream os = new FileOutputStream(entryFile)) {
                        byte[] buffer = new byte[4096];
                        int len;
                        while ((len = is.read(buffer)) != -1) {
                            os.write(buffer, 0, len);
                        }
                    }
                }
            }
        }
    }

    /**
     * 压缩文件为ZIP（生成OFD）
     */
    private static void zip(File sourceDir, File zipFile) throws IOException {
        try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile))) {
            zipDirectory(sourceDir, sourceDir, zos);
        }
    }

    private static void zipDirectory(File rootDir, File sourceDir, ZipOutputStream zos) throws IOException {
        File[] files = sourceDir.listFiles();
        if (files == null) return;

        for (File file : files) {
            if (file.isDirectory()) {
                zipDirectory(rootDir, file, zos);
            } else {
                String entryName = rootDir.toPath().relativize(file.toPath()).toString()
                        .replace(File.separator, "/");
                ZipEntry entry = new ZipEntry(entryName);
                zos.putNextEntry(entry);
                try (InputStream is = new FileInputStream(file)) {
                    byte[] buffer = new byte[4096];
                    int len;
                    while ((len = is.read(buffer)) != -1) {
                        zos.write(buffer, 0, len);
                    }
                }
                zos.closeEntry();
            }
        }
    }

    /**
     * 删除目录
     */
    private static void deleteDir(File dir) {
        if (dir.isDirectory()) {
            File[] files = dir.listFiles();
            if (files != null) {
                for (File file : files) {
                    deleteDir(file);
                }
            }
        }
        dir.delete();
    }

    /**
     * XML特殊字符转义
     */
    private static String escapeXml(String value) {
        if (value == null) return "";
        return value.replace("&", "&amp;")
                .replace("<", "&lt;")
                .replace(">", "&gt;")
                .replace("\"", "&quot;")
                .replace("'", "&apos;");
    }
}
